home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / win / c / regexp.com / WSSRX1.TXT < prev   
Encoding:
Text File  |  1989-09-20  |  43.7 KB  |  1,686 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.                               REGULAR EXPRESSION DLL
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.                               A Dynamic Link Library
  30.  
  31.                               for Microsoft Windows
  32.  
  33.                            by Windfall Software Systems
  34.  
  35.                                  40 Windfall Lane
  36.  
  37.                                 Marlboro, NJ 07746
  38.  
  39.  
  40.  
  41.                             CompuServe ID: 71330,3614
  42.  
  43.  
  44.  
  45.  
  46.                     Copyright Windfall Software Systems, 1989
  47.  
  48.                                All Rights Reserved
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.               A. Software License                                    1
  82.  
  83.               B. Concepts and Facilities                             2
  84.  
  85.                   1. Package Contents                                2
  86.                   2. Regular Expressions                             3
  87.                   3. Sample Regular Expressions                      5
  88.  
  89.               C. Functions Overview                                  8
  90.  
  91.               D. Applications                                       10
  92.  
  93.               E. Demonstration Program                              13
  94.  
  95.               F. Function Reference                                 14
  96.  
  97.                   1. RxMatch - Match a Regular Expression           15
  98.                   2. RxExtract - Extract a Matching Group           17
  99.                   3. RxReplace - Replace Placeholders               19
  100.                   4. RxMsgText - Build Error Message                21
  101.  
  102.               G. Registration Form                                  23
  103.  
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112.  
  113.  
  114.  
  115.  
  116.  
  117.  
  118.  
  119.  
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.           A. SOFTWARE LICENSE
  138.  
  139.  
  140.  
  141.           You  are   granted  a  limited  licence  to  use  the  Regular
  142.           Expression DLL  on a private, non-commercial basis and to make
  143.           copies of  this package  and distribute  them to  other users,
  144.           under the following conditions:
  145.  
  146.              ■ This  package   must  be  copied  and/or  distributed  in
  147.                unmodified form,  complete with  the file containing this
  148.                licence information.
  149.  
  150.              ■ No  fees  or  other  compensation  may  be  requested  or
  151.                accepted by  any licensee,  except that  clubs  and  user
  152.                groups may  charge a  nominal fee  not to  exceed $10 for
  153.                expenses and handling.
  154.  
  155.              ■ No part  of the software contained in this package can be
  156.                distributed with any other product or service.
  157.  
  158.           If you  want to  use this software in a different way, you can
  159.           use  this  package  for  evaluation  only.  If  it  fits  your
  160.           requirements, you can obtain a typical nonexclusive licence to
  161.           use the  software  and  related  documentation,  on  a  single
  162.           computer at a time, and distribute derivative works. To obtain
  163.           this licence,  mail the  Registration Form  (last page)  and a
  164.           registration fee  of $10 to the address shown on the form. The
  165.           licence will  be mailed  to you. You can also use this form to
  166.           order the  complete  source  code  of  this  package  and  its
  167.           internal documentation.
  168.  
  169.  
  170.  
  171.               You, the  Customer,  assume  all  responsibility  for  the
  172.           selection of  this  package  as  appropriate  to  achieve  the
  173.           results intended  by the Customer. The software of the Regular
  174.           Expression DLL  is provided  "as is"  without warranty  of any
  175.           kind, either  expressed or implied, including, but not limited
  176.           to the implied warranties of merchantability and fitness for a
  177.           particular purpose. In no event will Windfall Software Systems
  178.           be liable  for any  damages arising out of the Customer use of
  179.           the software,  including, loss of data or profits, loss of use
  180.           or other economic loss, or indirect, incidental, consequential
  181.           or special  damages of  any kind,  even if  Windfall  Software
  182.           Systems has been advised of the possibility of the same. In no
  183.           event shall  Windfall  Software  Systems'  liability  for  any
  184.           damages exceed  the price  paid for  the license  to  use  the
  185.           software, regardless of the form of the claim.
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.                                         1
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.           B. CONCEPTS AND FACILITIES
  204.  
  205.  
  206.  
  207.           This package constitutes a dynamic link library facility (DLL)
  208.           designed to  perform regular  expression  searches  and  other
  209.           related operations in a Windows application.
  210.  
  211.               A regular expression is a string that defines a pattern of
  212.           text  by  using  certain  special  characters.  Those  special
  213.           characters let  you specify  optional choices, repetitions and
  214.           character  classes   in  such  a  way  that  a  given  regular
  215.           expression matches  not one string but all strings having some
  216.           selected properties.
  217.  
  218.               Regular expressions  are often  supported by text editors.
  219.           Most likely,  the one  you use  provides a  generalized search
  220.           command that  uses some  form of regular expressions to define
  221.           text patterns.
  222.  
  223.               Although programmers make use of regular expressions while
  224.           editing programs  and using other programming tools, it is not
  225.           a common  practice to  use regular  expression routines in the
  226.           applications coming out from this work. Yet, as we will try to
  227.           demonstrate in a few examples, regular expression routines can
  228.           simplify many typical operations.
  229.  
  230.  
  231.           1. Package Contents
  232.  
  233.           The following  files make  up the  evaluation version  of  the
  234.           package:
  235.  
  236.                ■ WSSRX1.TXT        Documentation (this file).
  237.  
  238.                ■ WSSRX1.EXE        Dynamic link library.
  239.  
  240.                ■ WSSRX1.LIB        Import library for WSSRX1.EXE.
  241.  
  242.                ■ WSSRX.H           Interface definitions/declarations.
  243.  
  244.                ■ RXTEST.EXE        Demonstration program.
  245.  
  246.           The header  file (WSSRX.H) and the import library (WSSRX1.LIB)
  247.           are necessary  to compile  and  link  programs  that  use  the
  248.           dynamic link  library. The header file should be copied to the
  249.           directory pointed  by the  INCLUDE environment  variable.  The
  250.           import  library   -  to  the  directory  defined  by  the  LIB
  251.           environment variable.  This is  the  simplest  setup.  If  you
  252.           choose different  directories, you  will have  to  adjust  the
  253.  
  254.  
  255.  
  256.  
  257.  
  258.  
  259.                                         2
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.           #include directives  and the  linker parameters.  The  library
  269.           itself (WSSRX1.EXE) is the only component needed by a compiled
  270.           program.
  271.  
  272.  
  273.           2. Regular Expressions
  274.  
  275.           Regular  expressions   describe  more  or  less  complex  text
  276.           patterns. A  simple pattern  is merely a character, such as x,
  277.           or a  string of  characters  taken  literally,  such  as  ABC.
  278.           Regular expressions  like  that  represent  specific  strings,
  279.           character for  character. More  complex patterns  use  special
  280.           characters that  represent not individual strings but specific
  281.           context.
  282.  
  283.               The following  items define elementary regular expressions
  284.           matching a single character:
  285.  
  286.              ■ An  ordinary   character  matches   itself.  An  ordinary
  287.                character is  a character other than one of the following
  288.                special characters:
  289.  
  290.                     \ ^ $ . [ | { } * + ?
  291.  
  292.              ■ A backslash  (\) followed  by a  character  matches  that
  293.                character, even  if the  character alone is special. Note
  294.                that the  C language  uses this  character in  a  similar
  295.                fashion,  so  to  specify  a  backslash  in  a  C  string
  296.                constant, you have to use it twice, e.g. "\\{".
  297.  
  298.              ■ A caret  (^) matches itself except when it appears at the
  299.                beginning of  the entire  regular expression. The meaning
  300.                of this character at the beginning is defined later.
  301.  
  302.              ■ A dollar sign ($) matches itself except when it   appears
  303.                at the  end of the entire regular expression. The meaning
  304.                of this character at the end is defined later.
  305.  
  306.              ■ A period (.) matches any character.
  307.  
  308.              ■ A non-empty  string enclosed  in square  brackets ([]) is
  309.                called a character class. It matches any one character in
  310.                that string.  If, however,  the first  character  of  the
  311.                string is  a caret  (^), the  character class matches any
  312.                character except  the characters in the string. The caret
  313.                represents itself  when it  appears somewhere else in the
  314.                string. The  minus sign  (-) may  be used  to represent a
  315.                range  of   consecutive  characters.   For  example,  a-z
  316.                represents a  lower case  character. The minus represents
  317.                itself when  it appears  first (possibly after an initial
  318.                caret) or  last in  the string.  The right square bracket
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.                                         3
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.                stands for itself if it is the first character within the
  335.                string (after  an  initial  caret,  if  any).  All  other
  336.                characters defined  above as special represent themselves
  337.                in a  character class  (e.g.  [\.]  means  "backslash  or
  338.                period").
  339.  
  340.  
  341.  
  342.           The following  rules can be used recursively to construct more
  343.           complicated regular expressions:
  344.  
  345.              ■ An elementary  regular expression is a regular expression
  346.                matching a single character as described earlier.
  347.  
  348.              ■ A concatenation  of  regular  expressions  is  a  regular
  349.                expression that  matches  the  concatenation  of  strings
  350.                matched by each component of the concatenation.
  351.  
  352.              ■ An alternative, i.e. two regular expressions separated by
  353.                an |,  is a  regular expression  that  matches  a  string
  354.                matched by  at least  one  of  the  components.  If  both
  355.                components match,  the preference  is given  to the  left
  356.                one.
  357.  
  358.              ■ A group,  i.e. a  regular expression  enclosed in  braces
  359.                ({}), is  a regular  expression  that  matches  the  same
  360.                string as the enclosed expression.
  361.  
  362.              ■ An iteration,  i.e. an elementary regular expression or a
  363.                group  followed   by  an   asterisk  (*),  is  a  regular
  364.                expression that  matches zero  or more occurrences of the
  365.                string matched  by the expression preceding the asterisk.
  366.                If there  is any choice, the longest leftmost string that
  367.                facilitates a match is chosen.
  368.  
  369.              ■ A  non-empty   iteration,  i.e.   an  elementary  regular
  370.                expression or  a group  followed by  a  plus  (+),  is  a
  371.                regular expression  that matches  one or more occurrences
  372.                of the  string matched  by the  expression preceding  the
  373.                plus. If there is any choice, the longest leftmost string
  374.                that facilitates a match is chosen.
  375.  
  376.              ■ An option,  i.e. an  elementary regular  expression or  a
  377.                group followed  by a  question mark  (?),  is  a  regular
  378.                expression that  matches zero  or one  occurrence of  the
  379.                string matched  by the  expression preceding the question
  380.                mark. If there is a choice, the match with one occurrence
  381.                is chosen.
  382.  
  383.              ■ A caret  (^) at  the beginning  of a  regular  expression
  384.                constrains the match to an initial segment of a string.
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.                                         4
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.              ■ A dollar  sign ($)  at the  end of  a regular  expression
  401.                constrains the match to a final segment of a string.
  402.  
  403.           The above  rules introduce some special characters that behave
  404.           like operators and establish the precedence criteria for them.
  405.           For example,  because iterations  bind  single  characters  or
  406.           groups, a|b+  matches a  single a or one or more b's. To match
  407.           one or  more a's  or one  or more  b's, we  would have  to use
  408.           {a|b}+. Note,  that a  caret and  a dollar  sign are  somewhat
  409.           different than  other operators.  They do not have any special
  410.           meaning unless the stand on the beginning or end.
  411.  
  412.  
  413.           3. Sample Regular Expressions
  414.  
  415.           Each of the examples below consists of three parts:
  416.  
  417.                regular expression
  418.  
  419.                one or more strings to be matched against that expression
  420.  
  421.                explanation
  422.  
  423.           The matching  part of each sample string is shown to the right
  424.           of the string.
  425.  
  426.  
  427.  
  428.           [a-zA-Z0-9]
  429.  
  430.           (((ABC)))           A
  431.  
  432.           Matches a single letter or digit.
  433.  
  434.  
  435.  
  436.           [a-zA-Z0-9]+
  437.  
  438.           (((ABC)))           ABC
  439.  
  440.           201-777-1212        201
  441.  
  442.           Matches a  "word", i.e.  a string  of  letters  and/or  digits
  443.           delimited by something else.
  444.  
  445.  
  446.  
  447.           [a-zA-Z][a-zA-Z0-9]*
  448.  
  449.           (32, -x2)           x2
  450.  
  451.  
  452.  
  453.  
  454.  
  455.  
  456.  
  457.                                         5
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.           Matches an  ALGOL-like identifier,  i.e. a  string of  letters
  467.           and/or digits starting with a letter.
  468.  
  469.  
  470.  
  471.           Y{AB|CD}Z
  472.  
  473.           XXYCDZXX            YCDZ
  474.  
  475.           Matches YABZ or YCDZ.
  476.  
  477.  
  478.  
  479.           [a-zA-Z]*{ie|ei}[a-zA-Z]*
  480.  
  481.           selected properteis      properteis
  482.  
  483.           Matches words,  i.e. strings of letters, that contain ie or ei
  484.           (and are often misspelled).
  485.  
  486.  
  487.  
  488.           [0-9]+{\.[0-9]+}?{E{+|-}?[0-9]+}?
  489.  
  490.           - 12.79;            12.79
  491.  
  492.           a = 3.14E-2,        3.14E-2
  493.  
  494.           Matches a  decimal number  with an  optional fraction  and  an
  495.           optional  exponent.   As  you   will  see  later,  the  groups
  496.           surrounded by  braces not  only establish  scopes  for  the  ?
  497.           operators but also can be used to extract parts of the matched
  498.           number.
  499.  
  500.  
  501.  
  502.           [a-z]*[,.?!]?
  503.  
  504.           xxx, yyyy.          xxx,
  505.  
  506.           1234567890          match on a null string
  507.  
  508.           Matches a  possibly empty  string of  letters followed  by  an
  509.           optional delimiter?  Yes, but most likely this is not what you
  510.           want. This  pattern will show a match with any string, because
  511.           all  of  its  parts  are  optional.  It  may  match  something
  512.           non-trivial  if   the  test   string  starts  with  the  right
  513.           combination of  characters. Otherwise, it will match the empty
  514.           string that exists at the beginning of any string. All strings
  515.           start with  "a possibly empty string of letters followed by an
  516.           optional delimiter". Be careful with the ? and * operators. In
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.                                         6
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.           most cases, they have to be used within some non-empty context
  533.           to yield  good results. Sometimes, you can use them in the way
  534.           presented here  but you should check if the matching substring
  535.           is non-empty. In both cases shown above, the library indicates
  536.           a match.  To find  out that the match is non-trivial, you have
  537.           to check if the size of the matching string is nonzero.
  538.  
  539.  
  540.  
  541.  
  542.  
  543.  
  544.  
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551.  
  552.  
  553.  
  554.  
  555.  
  556.  
  557.  
  558.  
  559.  
  560.  
  561.  
  562.  
  563.  
  564.  
  565.  
  566.  
  567.  
  568.  
  569.  
  570.  
  571.  
  572.  
  573.  
  574.  
  575.  
  576.  
  577.  
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586.  
  587.  
  588.  
  589.                                         7
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.           C. FUNCTIONS OVERVIEW
  600.  
  601.  
  602.  
  603.           The primary  function in this library is the RxMatch function.
  604.           This function  searches a given string looking for a substring
  605.           that  matches  a  given  regular  expression.  This  operation
  606.           consists of  two steps. First, the function parses the regular
  607.           expression  and  converts  it  into  an  internal  form  which
  608.           facilitates  faster  matching.  This  step  may  fail  if  the
  609.           function discovers  a syntax  error in the regular expression.
  610.           If the parsing is successful, the next step tries to match the
  611.           internal form  of the  expression with  the given  string.  If
  612.           there is a matching substring, the function returns a non-zero
  613.           value. Otherwise, it returns zero.
  614.  
  615.               A call  to the  RxMatch function always supplies a regular
  616.           expression and  a string  to match. However, to avoid repeated
  617.           parsing of the same regular expression, the library provides a
  618.           caching facility.  The cache  holds a  number of recently used
  619.           regular expressions,  together with their translations. If the
  620.           expression supplied  in the current call is the same as one in
  621.           the cache, the parsing is bypassed. The cache capacity depends
  622.           on the  size of  the regular  expressions held in it and their
  623.           complexity. For  typical applications,  you can  assume that a
  624.           few most recent expressions will be found in the cache.
  625.  
  626.               The RxMatch  function can  respond with  more  information
  627.           than just  a boolean  return value. Its first parameter points
  628.           to an  area  (provided  by  the  calling  program)  where  the
  629.           function places the additional  information. This area, called
  630.           the feedback array, consists of 1-16 elements of the following
  631.           type:
  632.  
  633.                typedef
  634.                struct
  635.                   {
  636.                   int  pos;
  637.                   int  size;
  638.                   } RX;
  639.  
  640.           When an  RxMatch call  is unsuccessful because no match exists
  641.           the feedback  array is  cleared to zeros. However, if the call
  642.           failed due  to some formal errors in the regular expression, a
  643.           nonzero error  code is  inserted into  the first  word of  the
  644.           array (rx[0].pos). The error code can be converted into a text
  645.           message by the RxMsgText function.
  646.  
  647.               A successful  call to RxMatch places the relative position
  648.           and the  size of  the matched  substring in  the pos  and size
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.                                         8
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.           fields of  the first  feedback array  element.  The  remaining
  665.           elements receive  the positions  and sizes  of the  substrings
  666.           that match groups in the regular expression. For example, when
  667.           we match:
  668.  
  669.                {[0-9]*}A+{[0-9]*}  with  XXX5678AAA876...
  670.  
  671.           the feedback array will have the following elements:
  672.  
  673.                 3; 10   - position and size of the match (5678AAA876)
  674.                 3;  4   - first group (5678)
  675.                10;  3   - second group (876).
  676.  
  677.           The feedback  array, filled  up  by  a  call  to  the  RxMatch
  678.           function, can be used by subsequent calls to the RxExtract and
  679.           RxReplace functions.  The RxExtract function copies one of the
  680.           substrings identified  by the match into another field. It can
  681.           extract the  whole match  or  a  group  match.  The  RxReplace
  682.           function operates  a little  bit like the sprintf function. It
  683.           replaces placeholders  in a  given string  with  the  matching
  684.           substring and/or the group matches.
  685.  
  686.           Naming conventions
  687.  
  688.           In variables  and parameters , we use the prefix lsz to denote
  689.           a long  pointer to  a zero terminated character string and the
  690.           prefix rx  for an feedback array (RX []). Otherwise, we follow
  691.           the conventions from the Windows SDK.
  692.  
  693.  
  694.  
  695.  
  696.  
  697.  
  698.  
  699.  
  700.  
  701.  
  702.  
  703.  
  704.  
  705.  
  706.  
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713.  
  714.  
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721.                                         9
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.           D. APPLICATIONS
  732.  
  733.  
  734.  
  735.  
  736.           1. Elimination of trailing white-space
  737.  
  738.           Truncate a  given null-terminated  character  string  lszText,
  739.           eliminating all trailing white-space characters.
  740.  
  741.                RX     rx[1];
  742.  
  743.                if (RxMatch(rx,1,"[ \t\n\v\f\r]+$",lszText))
  744.                   lszText[rx[0].pos] = '\0';
  745.  
  746.           Note that  there is  a blank character at the beginning of the
  747.           character class.  The escape  sequences  define  respectively:
  748.           tab, new  line, vertical  tab, form  feed and carriage return.
  749.           They have  nothing to  do with  the escape  sequences used  by
  750.           regular expressions.  During compilation, the compiler changes
  751.           them into  the corresponding  ASCII codes. When the RxMatch is
  752.           called, the  character  class  will  contain  six  characters:
  753.           blank, tab, new line, etc. We use the $ at the end to restrict
  754.           the eventual match to the end of the tested string.
  755.  
  756.  
  757.           2. Reduction of white-space
  758.  
  759.           In a given, null-terminated, character string lszText, replace
  760.           each sequence of white-space characters with a single space.
  761.  
  762.                LPSTR  lpx;
  763.                RX     rx[1];
  764.  
  765.                lpx = lszText;
  766.                while (RxMatch(rx,1,"[ \t\n\v\f\r][ \t\n\v\f\r]+",lpx))
  767.                     {
  768.                     lpx += rx[0].pos;
  769.                     *lpx++ = ' ';
  770.                     lstrcpy(lpx,lpx + rx[0].size);
  771.                     }
  772.  
  773.           In this  example the  regular expression  matches two  or more
  774.           white-space characters.  The feedback array is used to gain to
  775.           the string and shrink it at the match point.
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.                                         10
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.           3. Parsing of a filename
  797.  
  798.           Assuming that a string lpFile contains a DOS file name, divide
  799.           it into  components: drive  specification (X:),  path (A\B\C\)
  800.           and name proper. All of the components are optional.
  801.  
  802.                if (RxMatch(rx,4,"{.:}?{.*}{[^\\\\]+} *",lpFile))
  803.                     {
  804.                     RxExtract(rx,1,lpFile,szDrive,sizeof(szDrive));
  805.                     RxExtract(rx,2,lpFile,szPath,sizeof(szPath));
  806.                     RxExtract(rx,3,lpFile,szName,sizeof(szName));
  807.                     }
  808.  
  809.           The first  group matches  an optional  drive designation.  The
  810.           last group  matches whatever follows the last backslash or, if
  811.           there  is  no  backslash,  anything  that  follows  the  drive
  812.           designation. The  middle group  matches everything  in between
  813.           (i.e. strings like xxx\yyy\). The iteration at the end removes
  814.           trailing spaces from the third group. Note, that this is not a
  815.           test that  lpFile contains  a valid  file name.  The RxExtract
  816.           calls extract  the group  matches and  place them  in szDrive,
  817.           szPath and szName.
  818.  
  819.  
  820.           4. Validation of input
  821.  
  822.           Check if a given input field szIn contains a valid hexadecimal
  823.           number and extract its components for further processing.
  824.  
  825.                char  szHex[10];
  826.                RX    rx[3];
  827.                int   value;
  828.  
  829.                if (RxMatch(rx,3,"^ *{[+-]?} *{[0-9a-fA-F]*} *$",szIn))
  830.                   {
  831.                   RxExtract(rx,2,szIn,szHex,sizeof(szHex));
  832.                   --- convert szHex to value ---
  833.                   if (rx[1].size && szIn[rx[1].pos] == '-')
  834.                      value = -value;
  835.                   }
  836.                else
  837.                   --- error - invalid input ---
  838.  
  839.           Here we anchored the match with ^$ so that the whole string is
  840.           checked. Any  extraneous characters  (e.g. "-5b x" or "+ -25")
  841.           will cause  a mismatch.  Spaces are  accepted on both ends and
  842.           after an optional sign. The feedback array is used to check if
  843.           the number is negative.
  844.  
  845.  
  846.  
  847.  
  848.  
  849.  
  850.  
  851.  
  852.  
  853.                                         11
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.           5. Format change
  863.  
  864.           Check if a given input field szIn contains two decimal numbers
  865.           separated with  a comma  and/or spaces.  If it  does, transfer
  866.           them into another field with the following format:
  867.  
  868.              Length=x, Width=y
  869.  
  870.           where x and y are the numbers extracted from szIn.
  871.  
  872.                char  szAux[50];     /* The output field  */
  873.                RX    rx[4];
  874.  
  875.                if (RxMatch(rx,4,"^ *{[0-9]+} *{,| } *{[0-9]+} *$",szIn))
  876.                   {
  877.                   strcpy(szAux,"Length=%1, Width=%3");
  878.                   RxReplace(rx,4,szIn,szAux,sizeof(szAux));
  879.                   }
  880.                else
  881.                   --- error - invalid input ---
  882.  
  883.           In this  example we  use two  groups to  access the  data.  An
  884.           additional group  (i.e. {,|  }) is  used to override the usual
  885.           interpretation  of   the  regular  expression  operators.  The
  886.           alternative "comma  or space"  has to be enclosed in brackets.
  887.           Without them  the scope  of the | operator would be too large:
  888.           " *{[0-9]+} *,"  OR "  *{[0-9]+} *". The RxReplace function is
  889.           used to  replace  the  two  placeholders  (%1,  %3)  with  the
  890.           substrings matching the first and the third group.
  891.  
  892.  
  893.           6. Parsing of a telephone number
  894.  
  895.           Search a  given string  szText for  a substring  resembling  a
  896.           telephone number.
  897.  
  898.                static char szRex[] = "{(?[2-9][0-9][0-9])?}? *-? *"
  899.                                      "{[2-9][0-9][0-9]} *-? *"
  900.                                      "{[0-9][0-9][0-9][0-9]}";
  901.                RX    rx[4];
  902.  
  903.                if (RxMatch(rx,4,szRex,szText))
  904.                     {
  905.                     RxExtract(rx,1,lpText,lszArea,6);
  906.                     RxExtract(rx,2,lpText,lszExch,4);
  907.                     RxExtract(rx,3,lpText,lszNmbr,5);
  908.                     }
  909.  
  910.           When the  match is  successful, we  transfer  the  area  code,
  911.           exchange and  the last four digit number to the fields pointed
  912.           to by lszArea, lszExch, lszNmbr.
  913.  
  914.  
  915.  
  916.  
  917.  
  918.  
  919.                                         12
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.           E. DEMONSTRATION PROGRAM
  930.  
  931.  
  932.  
  933.           This simple  Windows application  (RXTEST.EXE) can  be used to
  934.           learn how  to compose  regular expressions  and what to expect
  935.           from the functions provided by the library.
  936.  
  937.               When you first start RXTEST, it displays a dialog box with
  938.           a number  of empty  text fields  and one button (Execute). You
  939.           can enter text into the top three fields. The remaining fields
  940.           are used by the program to display results. The description of
  941.           all the fields follows.
  942.  
  943.           Pattern
  944.  
  945.           A regular expression.
  946.  
  947.           Search area
  948.  
  949.           Any text  to be  searched for a substring matching the regular
  950.           expression entered in the Pattern field.
  951.  
  952.           Replacement area
  953.  
  954.           Text to be passed to the RxReplace function.
  955.  
  956.           Return code
  957.  
  958.           The return  value from  the RxMatch  function followed  by  an
  959.           error message.
  960.  
  961.           Replacement result
  962.  
  963.           Text produced  by the  RxReplace function from the text in the
  964.           replacement area field.
  965.  
  966.           0: 1: 2: 3: 4: 5: 6: 7:
  967.  
  968.           Texts extracted  from the  search area  field by the RxExtract
  969.           calls referencing  a group  with the  given number.  The first
  970.           group (number  0) is defined as the full match. The subsequent
  971.           groups are  defined  by  the  brackets  ({})  in  the  regular
  972.           expression.
  973.  
  974.           Use the  TAB/BACKTAB keys  to move  between  the  three  input
  975.           fields. Click  the EXECUTE  button or  press the  ENTER key to
  976.           perform the  match and  related  operations.  Using  different
  977.           combinations of  the input  values, you  can play with all the
  978.           functions in the library.
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.                                         13
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.           F. FUNCTION REFERENCE
  996.  
  997.  
  998.  
  999.           This chapter  contains a  list of  functions from  the Regular
  1000.           Expression  DLL.   The  documentation  for  each  function  is
  1001.           organized in the way similar to that used in the Windows SDK.
  1002.  
  1003.               All function prototypes and other related declarations are
  1004.           contained in  the header  file wssrx.h.  This header should be
  1005.           included (after  windows.h) into  all program files that refer
  1006.           to the  functions in the DLL. The actual format of the include
  1007.           directive depends on the placement of the file. For example:
  1008.  
  1009.                #include "wssrx.h"       current directory,
  1010.  
  1011.                #include <wssrx.h>       a directory defined by the         
  1012.                                         INCLUDE environment variable,
  1013.  
  1014.                #include <sub\wssrx.h>   a subdirectory SUB of the above
  1015.                                         directory.
  1016.  
  1017.           Usually, you  make direct  calls to  the library functions and
  1018.           use the  import library (wssrx1.lib) when linking the program.
  1019.           In this  case Windows  will perform  dynamic linking  when the
  1020.           program is  first loaded  into memory.  You can  defer dynamic
  1021.           linking using the following technique:
  1022.  
  1023.                HANDLE  hRx;             /* Library handle          */
  1024.                FARPROC lpfnRxMatch;     /* To the RxMatch function */
  1025.  
  1026.                hRx = LoadLibrary("WSSRX1.EXE");
  1027.                lpfnRxMatch = GetProcAddress(hRx,OV_RXMATCH);
  1028.                - - -
  1029.                if (lpfnRxMatch(rx,3,"[0-9]+",szInput))
  1030.                   {
  1031.                   - - -
  1032.                   }
  1033.                - - -
  1034.                FreeLibrary(hRx);
  1035.  
  1036.           The header  file wssrx.h  contains definitions of four symbols
  1037.           (OV_xxxxx) that  can be  used with  the GetProcAddress call to
  1038.           retrieve the addresses of the respective Rx functions.
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.                                         14
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.           1. RxMatch - Match a Regular Expression
  1061.  
  1062.  
  1063.  
  1064.  
  1065.           BOOL RxMatch(rx, nLim, lszRex, lszTxt)
  1066.  
  1067.           This function  searches the lszTxt string for a substring that
  1068.           matches the regular expression given by the lszRex string. The
  1069.           result of  the search  is reflected by the return value and by
  1070.           the values  set in  the feedback  array defined  by the rx and
  1071.           nLim parameters.
  1072.  
  1073.           Parameter           Type/Description
  1074.  
  1075.           rx                  RX FAR []  Specifies an area to be used as
  1076.                               the feedback array. If rx is NULL, no
  1077.                               feedback information is returned.
  1078.  
  1079.           nLim                int  Specifies the number of elements in
  1080.                               the feedback array rx. If nLim is zero or
  1081.                               negative, no feedback information is
  1082.                               returned.
  1083.  
  1084.           lszRex              LPSTR  Points to a null-terminated string
  1085.                               that specifies the regular expression.
  1086.  
  1087.           lszTxt              LPSTR  Points to a null-terminated string
  1088.                               that is to be matched with the regular
  1089.                               expression.
  1090.  
  1091.           a) Return Value
  1092.  
  1093.           The return  value specifies the outcome of the function. It is
  1094.           non-zero if the match was successful. Otherwise, it is zero.
  1095.  
  1096.           b) Comments
  1097.  
  1098.           The return  value of zero means that either there was no match
  1099.           with the  regular expression or the parameters received by the
  1100.           function were  invalid. These  two cases  can be distinguished
  1101.           only when the feedback array is non-empty (i.e. when rx is not
  1102.           NULL and nLim is greater than 0). When the parameters received
  1103.           by the  function are  in error, the function places a non-zero
  1104.           error code  in the  first word  of the  feedback  array.  When
  1105.           everything is  valid and  only the  match is unsuccessful, the
  1106.           function clears that word.
  1107.  
  1108.               All possible  values of the error codes are defined in the
  1109.           wssrx.h  header  file  as  ERR_xxxx  manifest  constants.  The
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.                                         15
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126.           RxMsgText function  can be  used to convert an error code to a
  1127.           text message.
  1128.  
  1129.               The feedback  array does not have to be initialized in any
  1130.           way before  the call  to RxMatch. Only the first 16 entries of
  1131.           the array  are effectively  used  by  the  functions  in  this
  1132.           library.
  1133.  
  1134.  
  1135.  
  1136.  
  1137.  
  1138.  
  1139.  
  1140.  
  1141.  
  1142.  
  1143.  
  1144.  
  1145.  
  1146.  
  1147.  
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.  
  1161.  
  1162.  
  1163.  
  1164.  
  1165.  
  1166.  
  1167.  
  1168.  
  1169.  
  1170.  
  1171.  
  1172.  
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.                                         16
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.           2. RxExtract - Extract a Matching Group
  1193.  
  1194.  
  1195.  
  1196.  
  1197.           LPSTR RxExtract(rx, nN, lszTxt, lszDst, nSize)
  1198.  
  1199.           This function  assumes that  the rx and lszTxt parameters have
  1200.           been used  as arguments  in a  successful  RxMatch  call.  The
  1201.           function copies  a substring of lszTxt (adding the terminating
  1202.           null character),  to the destination area specified by lszDst.
  1203.           The substring extracted by the function is defined as follows:
  1204.  
  1205.              ■ If  nN is  zero, it  is the  substring matching the whole
  1206.                regular expression in the RxMatch call.
  1207.  
  1208.              ■ If  nN is greater than zero, it is the substring matching
  1209.                the nN-th group of the regular expression. If no group in
  1210.                the regular  expression corresponds  to nN, the substring
  1211.                is empty.
  1212.  
  1213.           If the extracted substring (including the terminating null) is
  1214.           longer than the destination length (nSize), it is truncated to
  1215.           fit in the destination area.
  1216.  
  1217.           Parameter           Type/Description
  1218.  
  1219.           rx                  RX FAR []  Specifies an area used as a
  1220.                               feedback array in a successful RxMatch
  1221.                               call.
  1222.  
  1223.           nN                  int  Specifies a group number in the
  1224.                               regular expression used by the RxMatch
  1225.                               call. This value should not exceed the
  1226.                               value of the nLim argument passed to
  1227.                               RxMatch.
  1228.  
  1229.           lszTxt              LPSTR  Points to a null-terminated string
  1230.                               that has been matched with the regular
  1231.                               expression using the RxMatch call.
  1232.  
  1233.           lszDst              LPSTR  Points to the buffer that receives
  1234.                               the extracted substring.
  1235.  
  1236.           nSize               int  Specifies the number of characters
  1237.                               (including the last null character) that
  1238.                               can be copied to the buffer.
  1239.  
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247.  
  1248.  
  1249.                                         17
  1250.  
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.           a) Return Value
  1259.  
  1260.           The return  value points  to the  extracted substring (same as
  1261.           lszDst).
  1262.  
  1263.           b) Comments
  1264.  
  1265.           The extracted  substring is  always terminated  with the  null
  1266.           character. If the receiving buffer is too short to accommodate
  1267.           the entire  extracted substring,  the function  copies nSize-1
  1268.           leftmost characters and appends the null character.
  1269.  
  1270.  
  1271.  
  1272.  
  1273.  
  1274.  
  1275.  
  1276.  
  1277.  
  1278.  
  1279.  
  1280.  
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286.  
  1287.  
  1288.  
  1289.  
  1290.  
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298.  
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304.  
  1305.  
  1306.  
  1307.  
  1308.  
  1309.  
  1310.  
  1311.  
  1312.  
  1313.  
  1314.  
  1315.                                         18
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.           3. RxReplace - Replace Placeholders
  1325.  
  1326.  
  1327.  
  1328.  
  1329.           LPSTR RxReplace(rx, nLim, lszTxt, lszDst, nSize)
  1330.  
  1331.           This function  assumes that the rx, nLim and lszTxt parameters
  1332.           have been  used as arguments in a successful RxMatch call. The
  1333.           function modifies  the string  defined  by  lszDst,  replacing
  1334.           placeholders embedded in it with substrings extracted from the
  1335.           string defined by lszTxt.
  1336.  
  1337.               A placeholder  is a single hexadecimal digit (0,1,...,e,f)
  1338.           preceded by  the  percent  character  (e.g.  %2  or  %a).  The
  1339.           placeholder of  the form  %n is  replaced by  the substring of
  1340.           lszTxt determined as follows:
  1341.  
  1342.              ■ If  n is  zero, it  is the  substring matching  the whole
  1343.                regular expression in the RxMatch call.
  1344.  
  1345.              ■ If  n is  greater than zero, it is the substring matching
  1346.                the n-th  group of the regular expression. If no group in
  1347.                the regular expression corresponds to n, the substring is
  1348.                empty.
  1349.  
  1350.           If the  modified string  (including the  terminating null)  is
  1351.           longer than the destination length (nSize), it is truncated at
  1352.           the end to fit in the destination area.
  1353.  
  1354.           Parameter           Type/Description
  1355.  
  1356.           rx                  RX FAR []  Specifies an area used as a
  1357.                               feedback array in a successful RxMatch
  1358.                               call.
  1359.  
  1360.           nLim                int  Specifies the size of the rx array
  1361.                               used in the RxMatch call.
  1362.  
  1363.           lszTxt              LPSTR  Points to a null-terminated string
  1364.                               that has been matched with the regular
  1365.                               expression using the RxMatch call.
  1366.  
  1367.           lszDst              LPSTR  Points to the null-terminated
  1368.                               string that is to be modified.
  1369.  
  1370.           nSize               int  Specifies the number of characters
  1371.                               that can be used in the area defined by
  1372.                               lszDst.
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.                                         19
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.           a) Return Value
  1391.  
  1392.           The return  value points to the last position (the terminating
  1393.           null character)  of the modified string (lszDst). The value is
  1394.           NULL if  during the operation some characters were lost due to
  1395.           lack of free space in lszDst.
  1396.  
  1397.           b) Comments
  1398.  
  1399.           The RxReplace  function uses  the area  defined by  lszDst and
  1400.           nSize as  the only work area. It replaces the placeholders one
  1401.           by one  starting from  the left.  After each  replacement, the
  1402.           destination string  expands, shrinks  or does  not change  the
  1403.           length,  depending  on  what  replaces  the  placeholder.  The
  1404.           destination area should be large enough to accommodate any one
  1405.           of those intermediate results.
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.  
  1412.  
  1413.  
  1414.  
  1415.  
  1416.  
  1417.  
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423.  
  1424.  
  1425.  
  1426.  
  1427.  
  1428.  
  1429.  
  1430.  
  1431.  
  1432.  
  1433.  
  1434.  
  1435.  
  1436.  
  1437.  
  1438.  
  1439.  
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446.  
  1447.                                         20
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456.           4. RxMsgText - Build Error Message
  1457.  
  1458.  
  1459.  
  1460.  
  1461.           int RxMsgText(rx, lszMsg, nSize)
  1462.  
  1463.           This function  assumes that the rx parameter have been used as
  1464.           an argument  in an  unsuccessful RxMatch  call. If the RxMatch
  1465.           call failed  because of  errors, the function creates an error
  1466.           message in  the buffer defined by the lszMsg parameter. If the
  1467.           RxMatch was  unsuccessful because  there was no match with the
  1468.           regular expression,  the function  puts an empty string in the
  1469.           buffer.
  1470.  
  1471.           If the message text string (including the terminating null) is
  1472.           longer than  the buffer length (nSize), it is truncated at the
  1473.           end to fit in the buffer area.
  1474.  
  1475.           Parameter           Type/Description
  1476.  
  1477.           rx                  RX FAR []  Specifies an area used as a
  1478.                               feedback array in an unsuccessful RxMatch
  1479.                               call.
  1480.  
  1481.           lszDst              LPSTR  Points to the buffer that receives
  1482.                               the error message text.
  1483.  
  1484.           nSize               int  Specifies the number of characters
  1485.                               (including the last null character) that
  1486.                               can be copied to the buffer.
  1487.  
  1488.           a) Return Value
  1489.  
  1490.           The return value specifies the length of the error message. It
  1491.           is zero if there was no error condition detected.
  1492.  
  1493.           b) Comments
  1494.  
  1495.           The function can respond with one of the following messages:
  1496.  
  1497.              Rex or Txt parameter is NULL
  1498.  
  1499.              Rex too long
  1500.  
  1501.              {{{ }}} too deep
  1502.  
  1503.              Missing right brace
  1504.  
  1505.              Missing left brace
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513.                                         21
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.              Iteration (+*) on empty string
  1523.  
  1524.              Nested iteration
  1525.  
  1526.              Invalid range
  1527.  
  1528.              Missing right bracket
  1529.  
  1530.              Incomplete escape sequence
  1531.  
  1532.              Logic error
  1533.  
  1534.  
  1535.  
  1536.  
  1537.  
  1538.  
  1539.  
  1540.  
  1541.  
  1542.  
  1543.  
  1544.  
  1545.  
  1546.  
  1547.  
  1548.  
  1549.  
  1550.  
  1551.  
  1552.  
  1553.  
  1554.  
  1555.  
  1556.  
  1557.  
  1558.  
  1559.  
  1560.  
  1561.  
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567.  
  1568.  
  1569.  
  1570.  
  1571.  
  1572.  
  1573.  
  1574.  
  1575.  
  1576.  
  1577.  
  1578.  
  1579.                                         22
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.  
  1587.  
  1588.  
  1589.           G. REGISTRATION FORM
  1590.  
  1591.  
  1592.  
  1593.                Name           _____________________________________
  1594.  
  1595.                Company        _____________________________________
  1596.  
  1597.                Title          _____________________________________
  1598.  
  1599.                Address        _____________________________________
  1600.  
  1601.                City, State    ________________________ Zip ________
  1602.  
  1603.                Phone          _____________________________________
  1604.  
  1605.  
  1606.  
  1607.  
  1608.  
  1609.           Registration fee               # computers ____ x $10  ______
  1610.  
  1611.  
  1612.  
  1613.           Documentation and the source
  1614.           code on a disk - add:          # computers ____ x $15  ______
  1615.  
  1616.  
  1617.  
  1618.           TOTAL ...............................................  ______
  1619.  
  1620.  
  1621.  
  1622.  
  1623.  
  1624.                Diskette format for the source code (choose one)
  1625.  
  1626.                    5.25" disk _____       3.5" disk _____
  1627.  
  1628.  
  1629.  
  1630.  
  1631.  
  1632.           Mail this form with your payment to:
  1633.  
  1634.                Windfall Software Systems
  1635.  
  1636.                40 Windfall Lane
  1637.  
  1638.                Marlboro, NJ 07746
  1639.  
  1640.  
  1641.  
  1642.  
  1643.  
  1644.  
  1645.                                         23
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.          ----------------end-of-author's-documentation---------------
  1653.  
  1654.                         Software Library Information:
  1655.  
  1656.                    This disk copy provided as a service of
  1657.  
  1658.                         The Public (Software) Library
  1659.  
  1660.          We are not the authors of this program, nor are we associated
  1661.          with the author in any way other than as a distributor of the
  1662.          program in accordance with the author's terms of distribution.
  1663.  
  1664.          Please direct shareware payments and specific questions about
  1665.          this program to the author of the program, whose name appears
  1666.          elsewhere in  this documentation. If you have trouble getting
  1667.          in touch with the author,  we will do whatever we can to help
  1668.          you with your questions. All programs have been tested and do
  1669.          run.  To report problems,  please use the form that is in the
  1670.          file PROBLEM.DOC on many of our disks or in other written for-
  1671.          mat with screen printouts, if possible.  The P(s)L cannot de-
  1672.          bug programs over the telephone.
  1673.  
  1674.          Disks in the P(s)L are updated monthly, so if you did not get
  1675.          this disk  directly from the P(s)L,  you should be aware that
  1676.          the files in this set may no  longer be the current versions.
  1677.  
  1678.          For a copy of the latest monthly software library newsletter
  1679.          and a list of the 2,000+ disks in the library, call or write
  1680.  
  1681.                         The Public (Software) Library
  1682.                               P.O.Box 35705 - F
  1683.                            Houston, TX 77235-5705
  1684.                                (713) 665-7017
  1685.  
  1686.